/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package servlets;

import java.io.IOException;
import java.util.List;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import javabeans.JBCliente;
import javabeans.JBFuncion;
import javabeans.JBReserva;
import javabeans.JBTipoEntrada;
import javabeans.JBUsuario;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import persistencia.ISistema;

/**
 *
 * @author Administrador
 */
public class agregarReservaServlet extends HttpServlet {

    ISistema i;

    @Override
    public void init() throws ServletException {
        super.init();
        /*Se adquieren los parametros configurados en el deployment describer a 
         * nivel del contexto*/
        try {
            ServletContext context = this.getServletContext();
            i = persistencia.Fabrica.getPersistenciaSistema(context);

        } catch (Exception exc) {
            throw new UnavailableException("No se puedo instanciar el servlet" + exc.toString());
        }
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        try {
            JBFuncion funcion = (JBFuncion) session.getAttribute("funcionSeleccionada");

            /*Obtengo al cliente que esta en la session, y sus reservas*/
            JBUsuario usuario = (JBUsuario) session.getAttribute("login");
            JBCliente cliente = i.obtenerCliente(usuario.getCi());

            /*Establezco la fecha en que termina la funcion que se ha elegido*/
            Calendar cal = Calendar.getInstance();
            cal.setTime(funcion.getFecha());
            cal.add(Calendar.MINUTE, funcion.getDuracion());
            Date fechaFinFuncion = cal.getTime();

            boolean reservasSolapadas = false;

            /*Recorro la lista de reservas activas del cliente y corroboro que ninguna
            se solape con la funcion que se ha elegido, de ser asi, la variable
            reservasSolapadas será true*/
            for (JBReserva r : cliente.getReservas()) {
                if (!r.isCancelada() && !r.isVendida()) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(r.getFuncion().getFecha());
                    calendar.add(Calendar.MINUTE, r.getFuncion().getDuracion());
                    Date fechaFinFuncionActual = calendar.getTime();

                    if (fechaFinFuncion.after(r.getFuncion().getFecha()) || funcion.getFecha().before(fechaFinFuncionActual)) {
                        reservasSolapadas = true;

                    }
                }
            }

            /*Si no hay reservas solpadas*/
            if (!reservasSolapadas) {

                /*obtengo los tipos de entradas que estan en session*/
                JBTipoEntrada menor = (JBTipoEntrada) session.getAttribute("menor");
                JBTipoEntrada normal = (JBTipoEntrada) session.getAttribute("normal");
                JBTipoEntrada mayor = (JBTipoEntrada) session.getAttribute("mayor");

                /*obtengo la cantidad de cada tipo de entrada ingresada por el usuario*/
                int cantMenor = Integer.valueOf(request.getParameter("menor"));
                int cantNormal = Integer.valueOf(request.getParameter("normal"));
                int cantMayor = Integer.valueOf(request.getParameter("mayor"));

                int cantidadEntradas = cantMenor + cantNormal + cantMayor;

                /*Si la funcion posee la misma o mayor cantidad de entradas disponibles que las elegidas
                `por el usuario continuo, caso contrario explico el problema*/
                if (funcion.getCapacidad() >= cantidadEntradas) {

                    menor.setCantidad(cantMenor);
                    normal.setCantidad(cantNormal);
                    mayor.setCantidad(cantMayor);


                    JBReserva reserva = new JBReserva();
                    /*establezco la fecha de hoy a la reserva que se esta creando*/
                    reserva.setFecha(Calendar.getInstance().getTime());
                    reserva.setCancelada(false);
                    reserva.setVendida(false);
                    reserva.setFuncion(funcion);
                    List<JBTipoEntrada> entradas = new LinkedList<JBTipoEntrada>();
                    entradas.add(menor);
                    entradas.add(normal);
                    entradas.add(mayor);

                    //Entradas que quedarán en la funcion luego de la reserva
                    int entradasDisponibles = funcion.getCapacidad() - cantidadEntradas;

                    double costoTotal = 0;

                    for (JBTipoEntrada t : entradas) {
                        costoTotal += t.getCantidad() * t.getPrecio();
                    }

                    reserva.setTiposEntradas(entradas);
                    reserva.setCostoTotal(costoTotal);


                    if (i.salvarReserva(reserva, cliente.getCi()) > 0) {

                        if (i.restarCapacidadSala(funcion, entradasDisponibles) > 0) {
                            /*se liberan aquellos atributos usados en la generacion de la reserva*/
                            limpiarSession(session);
                            request.setAttribute("error", "La reserva se ha confirmado correctamente");
                            request.getRequestDispatcher("agregarReserva.jsp").forward(request, response);
                        } else {
                            request.setAttribute("error", "Error al descontar entradas a la sala");
                            request.getRequestDispatcher("agregarReserva.jsp").forward(request, response);
                        }
                        /*caso en que ocurre un error mientras se intenta salvar la reserva en la BD*/
                    } else {
                        request.setAttribute("error", "Ha ocurrido un error");
                        request.getRequestDispatcher("agregarReserva.jsp").forward(request, response);
                    }
                }
                /*caso en que se solapa una reserva activa con la que se desea realizar*/
            } else {
                request.setAttribute("error", "Usted ya tiene una reserva en el mismo horario");
                request.getRequestDispatcher("agregarReserva.jsp").forward(request, response);
            }
        } catch (Exception ex) {
            request.setAttribute("error", ex.getMessage());
            request.getRequestDispatcher("agregarReserva.jsp").forward(request, response);
        }
    }

    private void limpiarSession(HttpSession session) {
        if (session.getAttribute("menor") != null) {
            session.removeAttribute("menor");
        }

        if (session.getAttribute("normal") != null) {
            session.removeAttribute("normal");
        }

        if (session.getAttribute("mayor") != null) {
            session.removeAttribute("mayor");
        }

        if (session.getAttribute("cineSeleccionado") != null) {
            session.removeAttribute("cineSeleccionado");
        }
        if (session.getAttribute("peliculas") != null) {
            session.removeAttribute("peliculas");
        }
        if (session.getAttribute("peliculaSeleccionada") != null) {
            session.removeAttribute("peliculaSeleccionada");
        }
        if (session.getAttribute("funciones") != null) {
            session.removeAttribute("funciones");
        }
        if (session.getAttribute("funcionSeleccionada") != null) {
            session.removeAttribute("funcionSeleccionada");
        }
        if (session.getAttribute("cines") != null) {
            session.removeAttribute("cines");
        }
        if (session.getAttribute("peliculas") != null) {
            session.removeAttribute("peliculas");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
